1   /*                        __    __  __  __    __  ___
2    *                       \  \  /  /    \  \  /  /  __/
3    *                        \  \/  /  /\  \  \/  /  /
4    *                         \____/__/  \__\____/__/.ɪᴏ
5    * ᶜᵒᵖʸʳᶦᵍʰᵗ ᵇʸ ᵛᵃᵛʳ ⁻ ˡᶦᶜᵉⁿˢᵉᵈ ᵘⁿᵈᵉʳ ᵗʰᵉ ᵃᵖᵃᶜʰᵉ ˡᶦᶜᵉⁿˢᵉ ᵛᵉʳˢᶦᵒⁿ ᵗʷᵒ ᵈᵒᵗ ᶻᵉʳᵒ
6    */
7   package io.vavr.collection;
8   
9   import io.vavr.Function1;
10  import io.vavr.Tuple;
11  import io.vavr.control.Option;
12  import io.vavr.Tuple2;
13  import org.junit.Test;
14  
15  import java.math.BigDecimal;
16  import java.util.ArrayList;
17  import java.util.Arrays;
18  import java.util.Spliterator;
19  import java.util.function.Function;
20  import java.util.function.Predicate;
21  import java.util.stream.Collector;
22  
23  import static org.assertj.core.api.Assertions.assertThatThrownBy;
24  
25  /**
26   * Tests all methods defined in {@link Seq}.
27   */
28  public abstract class AbstractSeqTest extends AbstractTraversableRangeTest {
29  
30      // -- construction
31  
32      @Override
33      abstract protected <T> Collector<T, ArrayList<T>, ? extends Seq<T>> collector();
34  
35      @Override
36      abstract protected <T> Seq<T> empty();
37  
38      @Override
39      abstract protected <T> Seq<T> of(T element);
40  
41      @SuppressWarnings("unchecked")
42      @Override
43      abstract protected <T> Seq<T> of(T... elements);
44  
45      @Override
46      abstract protected <T> Seq<T> ofAll(Iterable<? extends T> elements);
47  
48      @Override
49      abstract protected Seq<Boolean> ofAll(boolean... elements);
50  
51      @Override
52      abstract protected Seq<Byte> ofAll(byte... elements);
53  
54      @Override
55      abstract protected Seq<Character> ofAll(char... elements);
56  
57      @Override
58      abstract protected Seq<Double> ofAll(double... elements);
59  
60      @Override
61      abstract protected Seq<Float> ofAll(float... elements);
62  
63      @Override
64      abstract protected Seq<Integer> ofAll(int... elements);
65  
66      @Override
67      abstract protected Seq<Long> ofAll(long... elements);
68  
69      @Override
70      abstract protected Seq<Short> ofAll(short... elements);
71  
72      @Override
73      abstract protected Seq<Character> range(char from, char toExclusive);
74  
75      @Override
76      abstract protected Seq<Character> rangeBy(char from, char toExclusive, int step);
77  
78      @Override
79      abstract protected Seq<Double> rangeBy(double from, double toExclusive, double step);
80  
81      @Override
82      abstract protected Seq<Integer> range(int from, int toExclusive);
83  
84      @Override
85      abstract protected Seq<Integer> rangeBy(int from, int toExclusive, int step);
86  
87      @Override
88      abstract protected Seq<Long> range(long from, long toExclusive);
89  
90      @Override
91      abstract protected Seq<Long> rangeBy(long from, long toExclusive, long step);
92  
93      @Override
94      abstract protected Seq<Character> rangeClosed(char from, char toInclusive);
95  
96      @Override
97      abstract protected Seq<Character> rangeClosedBy(char from, char toInclusive, int step);
98  
99      @Override
100     abstract protected Seq<Double> rangeClosedBy(double from, double toInclusive, double step);
101 
102     @Override
103     abstract protected Seq<Integer> rangeClosed(int from, int toInclusive);
104 
105     @Override
106     abstract protected Seq<Integer> rangeClosedBy(int from, int toInclusive, int step);
107 
108     @Override
109     abstract protected Seq<Long> rangeClosed(long from, long toInclusive);
110 
111     @Override
112     abstract protected Seq<Long> rangeClosedBy(long from, long toInclusive, long step);
113 
114     abstract protected <T> Seq<? extends Seq<T>> transpose(Seq<? extends Seq<T>> rows);
115 
116     // -- static narrow
117 
118     @Test
119     public void shouldNarrowSeq() {
120         final Seq<Double> doubles = of(1.0d);
121         final Seq<Number> numbers = Seq.narrow(doubles);
122         final int actual = numbers.append(new BigDecimal("2.0")).sum().intValue();
123         assertThat(actual).isEqualTo(3);
124     }
125 
126     // -- append
127 
128     @Test
129     public void shouldAppendElementToNil() {
130         final Seq<Integer> actual = this.<Integer> empty().append(1);
131         final Seq<Integer> expected = of(1);
132         assertThat(actual).isEqualTo(expected);
133     }
134 
135     @Test
136     public void shouldAppendNullElementToNil() {
137         final Seq<Integer> actual = this.<Integer> empty().append(null);
138         final Seq<Integer> expected = this.of((Integer) null);
139         assertThat(actual).isEqualTo(expected);
140     }
141 
142     @Test
143     public void shouldAppendElementToNonNil() {
144         final Seq<Integer> actual = of(1, 2).append(3);
145         final Seq<Integer> expected = of(1, 2, 3);
146         assertThat(actual).isEqualTo(expected);
147     }
148 
149     @Test
150     public void shouldMixAppendAndPrepend() {
151         assertThat(of(1).append(2).prepend(0).prepend(-1).append(3).append(4)).isEqualTo(of(-1, 0, 1, 2, 3, 4));
152     }
153 
154     // -- appendAll
155 
156     @Test(expected = NullPointerException.class)
157     public void shouldThrowOnAppendAllOfNull() {
158         empty().appendAll(null);
159     }
160 
161     @Test
162     public void shouldAppendAllNilToNil() {
163         final Seq<Object> actual = empty().appendAll(empty());
164         final Seq<Object> expected = empty();
165         assertThat(actual).isEqualTo(expected);
166     }
167 
168     @Test
169     public void shouldAppendAllNonNilToNil() {
170         final Seq<Integer> actual = this.<Integer> empty().appendAll(of(1, 2, 3));
171         final Seq<Integer> expected = of(1, 2, 3);
172         assertThat(actual).isEqualTo(expected);
173     }
174 
175     @Test
176     public void shouldAppendAllNilToNonNil() {
177         final Seq<Integer> actual = of(1, 2, 3).appendAll(empty());
178         final Seq<Integer> expected = of(1, 2, 3);
179         assertThat(actual).isEqualTo(expected);
180     }
181 
182     @Test
183     public void shouldAppendAllNonNilToNonNil() {
184         final Seq<Integer> actual = of(1, 2, 3).appendAll(of(4, 5, 6));
185         final Seq<Integer> expected = of(1, 2, 3, 4, 5, 6);
186         assertThat(actual).isEqualTo(expected);
187     }
188 
189     @Test
190     public void shouldReturnSameSeqWhenEmptyAppendAllEmpty() {
191         final Seq<Integer> empty = empty();
192         assertThat(empty.appendAll(empty())).isSameAs(empty);
193     }
194 
195     @Test
196     public void shouldReturnSameSeqWhenEmptyAppendAllNonEmpty() {
197         final Seq<Integer> seq = of(1, 2, 3);
198         assertThat(empty().appendAll(seq)).isSameAs(seq);
199     }
200 
201     @Test
202     public void shouldReturnSameSeqWhenNonEmptyAppendAllEmpty() {
203         final Seq<Integer> seq = of(1, 2, 3);
204         if (seq.hasDefiniteSize()) {
205             assertThat(seq.appendAll(empty())).isSameAs(seq);
206         } else {
207             assertThat(seq.appendAll(empty())).isEqualTo(seq);
208         }
209     }
210 
211     // -- apply
212 
213     @Test
214     public void shouldUseSeqAsPartialFunction() {
215         assertThat(of(1, 2, 3).apply(1)).isEqualTo(2);
216     }
217 
218     // -- combinations
219 
220     @Test
221     public void shouldComputeCombinationsOfEmptyList() {
222         assertThat(empty().combinations()).isEqualTo(of(empty()));
223     }
224 
225     @SuppressWarnings("unchecked")
226     @Test
227     public void shouldComputeCombinationsOfNonEmptyList() {
228         assertThat(of(1, 2, 3).combinations())
229                 .isEqualTo(of(empty(), of(1), of(2), of(3), of(1, 2), of(1, 3), of(2, 3), of(1, 2, 3)));
230     }
231 
232     // -- asJavaMutable*
233 
234     @Test
235     public void shouldConvertAsJava() {
236         final java.util.List<Integer> list = of(1, 2, 3).asJavaMutable();
237         list.add(4);
238         assertThat(list).isEqualTo(Arrays.asList(1, 2, 3, 4));
239     }
240 
241     @Test
242     public void shouldConvertAsJavaWithConsumer() {
243         final Seq<Integer> seq = of(1, 2, 3).asJavaMutable(list -> {
244             assertThat(list).isEqualTo(Arrays.asList(1, 2, 3));
245             list.add(4);
246         });
247         assertThat(seq).isEqualTo(of(1, 2, 3, 4));
248     }
249 
250     @Test
251     public void shouldConvertAsJavaAndRethrowException() {
252         assertThatThrownBy(() -> of(1, 2, 3).asJavaMutable(list -> { throw new RuntimeException("test");}))
253                 .isInstanceOf(RuntimeException.class)
254                 .hasMessage("test");
255     }
256 
257     @Test
258     public void shouldConvertAsJavaImmutable() {
259         final java.util.List<Integer> list = of(1, 2, 3).asJava();
260         assertThat(list).isEqualTo(Arrays.asList(1, 2, 3));
261         assertThatThrownBy(() -> list.add(4)).isInstanceOf(UnsupportedOperationException.class);
262     }
263 
264     @Test
265     public void shouldConvertAsJavaImmutableWithConsumer() {
266         final Seq<Integer> seq = of(1, 2, 3).asJava(list -> {
267             assertThat(list).isEqualTo(Arrays.asList(1, 2, 3));
268             assertThatThrownBy(() -> list.add(4)).isInstanceOf(UnsupportedOperationException.class);
269         });
270         assertThat(seq).isEqualTo(of(1, 2, 3));
271     }
272 
273     @Test
274     public void shouldConvertAsJavaImmutableAndRethrowException() {
275         assertThatThrownBy(() -> of(1, 2, 3).asJava(list -> { throw new RuntimeException("test");}))
276                 .isInstanceOf(RuntimeException.class)
277                 .hasMessage("test");
278     }
279 
280     // -- combinations(k)
281 
282     @Test
283     public void shouldComputeKCombinationsOfEmptyList() {
284         assertThat(empty().combinations(1)).isEmpty();
285     }
286 
287     @SuppressWarnings("unchecked")
288     @Test
289     public void shouldComputeKCombinationsOfNonEmptyList() {
290         assertThat(of(1, 2, 3).combinations(2)).isEqualTo(of(of(1, 2), of(1, 3), of(2, 3)));
291     }
292 
293     @Test
294     public void shouldComputeKCombinationsOfNegativeK() {
295         assertThat(of(1).combinations(-1)).isEqualTo(of(empty()));
296     }
297 
298     // -- containsSlice
299 
300     @Test
301     public void shouldRecognizeNilNotContainsSlice() {
302         final boolean actual = empty().containsSlice(of(1, 2, 3));
303         assertThat(actual).isFalse();
304     }
305 
306     @Test
307     public void shouldRecognizeNonNilDoesContainSlice() {
308         final boolean actual = of(1, 2, 3, 4, 5).containsSlice(of(2, 3));
309         assertThat(actual).isTrue();
310     }
311 
312     @Test
313     public void shouldRecognizeNonNilDoesNotContainSlice() {
314         final boolean actual = of(1, 2, 3, 4, 5).containsSlice(of(2, 1, 4));
315         assertThat(actual).isFalse();
316     }
317 
318     // -- crossProduct()
319 
320     @Test
321     public void shouldCalculateCrossProductOfNil() {
322         final Iterator<Tuple2<Object, Object>> actual = empty().crossProduct();
323         assertThat(actual).isEmpty();
324     }
325 
326     @SuppressWarnings("unchecked")
327     @Test
328     public void shouldCalculateCrossProductOfNonNil() {
329         final List<Tuple2<Integer, Integer>> actual = of(1, 2, 3).crossProduct().toList();
330         final List<Tuple2<Integer, Integer>> expected = List.of(Tuple.of(1, 1), Tuple.of(1, 2), Tuple.of(1, 3),
331                 Tuple.of(2, 1), Tuple.of(2, 2), Tuple.of(2, 3), Tuple.of(3, 1), Tuple.of(3, 2), Tuple.of(3, 3));
332         assertThat(actual).isEqualTo(expected);
333     }
334 
335     // -- crossProduct(int)
336 
337     @Test
338     public void shouldCalculateCrossProductPower() {
339         assertThat(of(1, 2).crossProduct(0).toList()).isEqualTo(List.of(empty()));
340         assertThat(of(1, 2).crossProduct(1).toList()).isEqualTo(List.of(of(1), of(2)));
341         assertThat(of(1, 2).crossProduct(2).toList()).isEqualTo(List.of(of(1, 1), of(1, 2), of(2, 1), of(2, 2)));
342     }
343 
344     @Test
345     public void shouldCrossProductPowerBeLazy() {
346         assertThat(range(0, 10).crossProduct(100).take(1).get()).isEqualTo(tabulate(100, i -> 0));
347     }
348 
349     @Test
350     public void shouldCrossProductOfNegativePowerBeEmpty() {
351         assertThat(of(1, 2).crossProduct(-1).toList()).isEqualTo(List.empty());
352     }
353 
354     // -- crossProduct(Iterable)
355 
356     @Test
357     public void shouldCalculateCrossProductOfNilAndNil() {
358         final Iterator<Tuple2<Object, Object>> actual = empty().crossProduct(empty());
359         assertThat(actual).isEmpty();
360     }
361 
362     @Test
363     public void shouldCalculateCrossProductOfNilAndNonNil() {
364         final Iterator<Tuple2<Object, Object>> actual = empty().crossProduct(of(1, 2, 3));
365         assertThat(actual).isEmpty();
366     }
367 
368     @Test
369     public void shouldCalculateCrossProductOfNonNilAndNil() {
370         final Iterator<Tuple2<Integer, Integer>> actual = of(1, 2, 3).crossProduct(empty());
371         assertThat(actual).isEmpty();
372     }
373 
374     @SuppressWarnings("unchecked")
375     @Test
376     public void shouldCalculateCrossProductOfNonNilAndNonNil() {
377         final List<Tuple2<Integer, Character>> actual = of(1, 2, 3).crossProduct(of('a', 'b')).toList();
378         final List<Tuple2<Integer, Character>> expected = of(Tuple.of(1, 'a'), Tuple.of(1, 'b'),
379                 Tuple.of(2, 'a'), Tuple.of(2, 'b'), Tuple.of(3, 'a'), Tuple.of(3, 'b')).toList();
380         assertThat(actual).isEqualTo(expected);
381     }
382 
383     @Test(expected = NullPointerException.class)
384     public void shouldThrowWhenCalculatingCrossProductAndThatIsNull() {
385         empty().crossProduct(null);
386     }
387 
388 
389     // -- dropRightUntil
390 
391     @Test
392     public void shouldDropRightUntilNoneOnNil() {
393         assertThat(empty().dropRightUntil(ignored -> true)).isSameAs(empty());
394     }
395 
396     @Test
397     public void shouldDropRightUntilNoneIfPredicateIsTrue() {
398         final Seq<Integer> values = of(1, 2, 3);
399         assertThat(values.dropRightUntil(ignored -> true)).isEqualTo(values);
400     }
401 
402     @Test
403     public void shouldDropRightUntilAllIfPredicateIsFalse() {
404         assertThat(of(1, 2, 3).dropRightUntil(ignored -> false)).isEqualTo(empty());
405     }
406 
407     @Test
408     public void shouldDropRightUntilCorrect() {
409         assertThat(of(1, 2, 3).dropRightUntil(i -> i <= 2)).isEqualTo(of(1, 2));
410     }
411 
412     // -- dropRightWhile
413 
414     @Test
415     public void shouldDropRightWhileNoneOnNil() {
416         assertThat(empty().dropRightWhile(ignored -> true)).isSameAs(empty());
417     }
418 
419     @Test
420     public void shouldDropRightWhileNoneIfPredicateIsFalse() {
421         final Seq<Integer> values = of(1, 2, 3);
422         assertThat(values.dropRightWhile(ignored -> false)).isEqualTo(values);
423     }
424 
425     @Test
426     public void shouldDropRightWhileAllIfPredicateIsTrue() {
427         assertThat(of(1, 2, 3).dropRightWhile(ignored -> true)).isEqualTo(empty());
428     }
429 
430     @Test
431     public void shouldDropRightWhileAccordingToPredicate() {
432         assertThat(of(1, 2, 3).dropRightWhile(i -> i > 2)).isEqualTo(of(1, 2));
433     }
434 
435     @Test
436     public void shouldDropRightWhileAndNotTruncate() {
437         assertThat(of(1, 2, 3).dropRightWhile(i -> i % 2 == 1)).isEqualTo(of(1, 2));
438     }
439 
440     // -- get
441 
442     @Test(expected = IndexOutOfBoundsException.class)
443     public void shouldThrowWhenGetWithNegativeIndexOnNil() {
444         empty().get(-1);
445     }
446 
447     @Test(expected = IndexOutOfBoundsException.class)
448     public void shouldThrowWhenGetWithNegativeIndexOnNonNil() {
449         of(1).get(-1);
450     }
451 
452     @Test(expected = IndexOutOfBoundsException.class)
453     public void shouldThrowWhenGetOnNil() {
454         empty().get(0);
455     }
456 
457     @Test(expected = IndexOutOfBoundsException.class)
458     public void shouldThrowWhenGetWithTooBigIndexOnNonNil() {
459         of(1).get(1);
460     }
461 
462     @Test
463     public void shouldGetFirstElement() {
464         assertThat(of(1, 2, 3).get(0)).isEqualTo(1);
465     }
466 
467     @Test
468     public void shouldGetLastElement() {
469         assertThat(of(1, 2, 3).get(2)).isEqualTo(3);
470     }
471 
472     // -- indexOf
473 
474     @Test
475     public void shouldNotFindIndexOfElementWhenSeqIsEmpty() {
476         assertThat(empty().indexOf(1)).isEqualTo(-1);
477 
478         assertThat(empty().indexOfOption(1)).isEqualTo(Option.none());
479     }
480 
481     @Test
482     public void shouldNotFindIndexOfElementWhenStartIsGreater() {
483         assertThat(of(1, 2, 3, 4).indexOf(2, 2)).isEqualTo(-1);
484 
485         assertThat(of(1, 2, 3, 4).indexOfOption(2, 2)).isEqualTo(Option.none());
486     }
487 
488     @Test
489     public void shouldFindIndexOfFirstElement() {
490         assertThat(of(1, 2, 3).indexOf(1)).isEqualTo(0);
491 
492         assertThat(of(1, 2, 3).indexOfOption(1)).isEqualTo(Option.some(0));
493     }
494 
495     @Test
496     public void shouldFindIndexOfInnerElement() {
497         assertThat(of(1, 2, 3).indexOf(2)).isEqualTo(1);
498 
499         assertThat(of(1, 2, 3).indexOfOption(2)).isEqualTo(Option.some(1));
500     }
501 
502     @Test
503     public void shouldFindIndexOfLastElement() {
504         assertThat(of(1, 2, 3).indexOf(3)).isEqualTo(2);
505 
506         assertThat(of(1, 2, 3).indexOfOption(3)).isEqualTo(Option.some(2));
507     }
508 
509     // -- indexOfSlice
510 
511     @Test
512     public void shouldNotFindIndexOfSliceWhenSeqIsEmpty() {
513         assertThat(empty().indexOfSlice(of(2, 3))).isEqualTo(-1);
514 
515         assertThat(empty().indexOfSliceOption(of(2, 3))).isEqualTo(Option.none());
516     }
517 
518     @Test
519     public void shouldNotFindIndexOfSliceWhenStartIsGreater() {
520         assertThat(of(1, 2, 3, 4).indexOfSlice(of(2, 3), 2)).isEqualTo(-1);
521 
522         assertThat(of(1, 2, 3, 4).indexOfSliceOption(of(2, 3), 2)).isEqualTo(Option.none());
523     }
524 
525     @Test
526     public void shouldFindIndexOfFirstSlice() {
527         assertThat(of(1, 2, 3, 4).indexOfSlice(of(1, 2))).isEqualTo(0);
528 
529         assertThat(of(1, 2, 3, 4).indexOfSliceOption(of(1, 2))).isEqualTo(Option.some(0));
530     }
531 
532     @Test
533     public void shouldFindIndexOfInnerSlice() {
534         assertThat(of(1, 2, 3, 4).indexOfSlice(of(2, 3))).isEqualTo(1);
535 
536         assertThat(of(1, 2, 3, 4).indexOfSliceOption(of(2, 3))).isEqualTo(Option.some(1));
537     }
538 
539     @Test
540     public void shouldFindIndexOfLastSlice() {
541         assertThat(of(1, 2, 3).indexOfSlice(of(2, 3))).isEqualTo(1);
542 
543         assertThat(of(1, 2, 3).indexOfSliceOption(of(2, 3))).isEqualTo(Option.some(1));
544     }
545 
546     // -- lastIndexOf
547 
548     @Test
549     public void shouldNotFindLastIndexOfElementWhenSeqIsEmpty() {
550         assertThat(empty().lastIndexOf(1)).isEqualTo(-1);
551 
552         assertThat(empty().lastIndexOfOption(1)).isEqualTo(Option.none());
553     }
554 
555     @Test
556     public void shouldNotFindLastIndexOfElementWhenEndIdLess() {
557         assertThat(of(1, 2, 3, 4).lastIndexOf(3, 1)).isEqualTo(-1);
558 
559         assertThat(of(1, 2, 3, 4).lastIndexOfOption(3, 1)).isEqualTo(Option.none());
560     }
561 
562     @Test
563     public void shouldFindLastIndexOfElement() {
564         assertThat(of(1, 2, 3, 1, 2, 3).lastIndexOf(1)).isEqualTo(3);
565 
566         assertThat(of(1, 2, 3, 1, 2, 3).lastIndexOfOption(1)).isEqualTo(Option.some(3));
567     }
568 
569     @Test
570     public void shouldFindLastIndexOfElementWithEnd() {
571         assertThat(of(1, 2, 3, 1, 2, 3).lastIndexOf(1, 1)).isEqualTo(0);
572 
573         assertThat(of(1, 2, 3, 1, 2, 3).lastIndexOfOption(1, 1)).isEqualTo(Option.some(0));
574     }
575 
576     // -- lastIndexOfSlice
577 
578     @Test
579     public void shouldNotFindLastIndexOfSliceWhenSeqIsEmpty() {
580         assertThat(empty().lastIndexOfSlice(of(2, 3))).isEqualTo(-1);
581 
582         assertThat(empty().lastIndexOfSliceOption(of(2, 3))).isEqualTo(Option.none());
583     }
584 
585     @Test
586     public void shouldNotFindLastIndexOfSliceWhenEndIdLess() {
587         assertThat(of(1, 2, 3, 4, 5).lastIndexOfSlice(of(3, 4), 1)).isEqualTo(-1);
588 
589         assertThat(of(1, 2, 3, 4, 5).lastIndexOfSliceOption(of(3, 4), 1)).isEqualTo(Option.none());
590     }
591 
592     @Test
593     public void shouldFindLastIndexOfSlice() {
594         assertThat(of(1, 2, 3, 1, 2).lastIndexOfSlice(empty())).isEqualTo(5);
595         assertThat(of(1, 2, 3, 1, 2).lastIndexOfSlice(of(2))).isEqualTo(4);
596         assertThat(of(1, 2, 3, 1, 2, 3, 4).lastIndexOfSlice(of(2, 3))).isEqualTo(4);
597         assertThat(of(1, 2, 3, 1, 2, 3).lastIndexOfSlice(of(1, 2, 3))).isEqualTo(3);
598 
599         assertThat(of(1, 2, 3, 1, 2).lastIndexOfSliceOption(empty())).isEqualTo(Option.some(5));
600         assertThat(of(1, 2, 3, 1, 2).lastIndexOfSliceOption(of(2))).isEqualTo(Option.some(4));
601         assertThat(of(1, 2, 3, 1, 2, 3, 4).lastIndexOfSliceOption(of(2, 3))).isEqualTo(Option.some(4));
602         assertThat(of(1, 2, 3, 1, 2, 3).lastIndexOfSliceOption(of(1, 2, 3))).isEqualTo(Option.some(3));
603     }
604 
605     @Test
606     public void shouldFindLastIndexOfSliceWithEnd() {
607         assertThat(empty().lastIndexOfSlice(empty(), -1)).isEqualTo(-1);
608         assertThat(empty().lastIndexOfSlice(empty(), 0)).isEqualTo(0);
609         assertThat(of(1, 2, 3, 1, 2, 3).lastIndexOfSlice(empty(), -1)).isEqualTo(-1);
610         assertThat(of(1, 2, 3, 1, 2, 3).lastIndexOfSlice(empty(), 2)).isEqualTo(2);
611         assertThat(of(1, 2, 3, 1, 2, 3).lastIndexOfSlice(of(2), -1)).isEqualTo(-1);
612         assertThat(of(1, 2, 3, 1, 2, 3).lastIndexOfSlice(of(2), 2)).isEqualTo(1);
613         assertThat(of(1, 2, 3, 1, 2, 3).lastIndexOfSlice(of(2, 3), 2)).isEqualTo(1);
614         assertThat(of(1, 2, 3, 1, 2, 3, 4).lastIndexOfSlice(of(2, 3), 2)).isEqualTo(1);
615         assertThat(of(1, 2, 3, 1, 2, 3).lastIndexOfSlice(of(1, 2, 3), 2)).isEqualTo(0);
616 
617         assertThat(empty().lastIndexOfSliceOption(empty(), -1)).isEqualTo(Option.none());
618         assertThat(empty().lastIndexOfSliceOption(empty(), 0)).isEqualTo(Option.some(0));
619         assertThat(of(1, 2, 3, 1, 2, 3).lastIndexOfSliceOption(empty(), -1)).isEqualTo(Option.none());
620         assertThat(of(1, 2, 3, 1, 2, 3).lastIndexOfSliceOption(empty(), 2)).isEqualTo(Option.some(2));
621         assertThat(of(1, 2, 3, 1, 2, 3).lastIndexOfSliceOption(of(2), -1)).isEqualTo(Option.none());
622         assertThat(of(1, 2, 3, 1, 2, 3).lastIndexOfSliceOption(of(2), 2)).isEqualTo(Option.some(1));
623         assertThat(of(1, 2, 3, 1, 2, 3).lastIndexOfSliceOption(of(2, 3), 2)).isEqualTo(Option.some(1));
624         assertThat(of(1, 2, 3, 1, 2, 3, 4).lastIndexOfSliceOption(of(2, 3), 2)).isEqualTo(Option.some(1));
625         assertThat(of(1, 2, 3, 1, 2, 3).lastIndexOfSliceOption(of(1, 2, 3), 2)).isEqualTo(Option.some(0));
626     }
627 
628     // -- indexWhere
629 
630     @Test
631     public void shouldCalculateIndexWhere() {
632         assertThat(of(0, 1, 2, -1, 0, 1, 2).indexWhere(i -> i == 0)).isEqualTo(0);
633         assertThat(of(0, 1, 2, -1, 0, 1, 2).indexWhere(i -> i == 1)).isEqualTo(1);
634         assertThat(of(0, 1, 2, -1, 0, 1, 2).indexWhere(i -> i == 2)).isEqualTo(2);
635         assertThat(of(0, 1, 2, -1, 0, 1, 2).indexWhere(i -> i == 8)).isEqualTo(-1);
636         assertThat(of(0, 1, 2, -1, 0, 1, 2).indexWhere(i -> i == 0, 3)).isEqualTo(4);
637         assertThat(of(0, 1, 2, -1, 0, 1, 2).indexWhere(i -> i == 1, 3)).isEqualTo(5);
638         assertThat(of(0, 1, 2, -1, 0, 1, 2).indexWhere(i -> i == 2, 3)).isEqualTo(6);
639         assertThat(of(0, 1, 2, -1, 0, 1, 2).indexWhere(i -> i == 8, 3)).isEqualTo(-1);
640 
641         assertThat(of(0, 1, 2, -1, 0, 1, 2).indexWhereOption(i -> i == 0)).isEqualTo(Option.some(0));
642         assertThat(of(0, 1, 2, -1, 0, 1, 2).indexWhereOption(i -> i == 1)).isEqualTo(Option.some(1));
643         assertThat(of(0, 1, 2, -1, 0, 1, 2).indexWhereOption(i -> i == 2)).isEqualTo(Option.some(2));
644         assertThat(of(0, 1, 2, -1, 0, 1, 2).indexWhereOption(i -> i == 8)).isEqualTo(Option.none());
645         assertThat(of(0, 1, 2, -1, 0, 1, 2).indexWhereOption(i -> i == 0, 3)).isEqualTo(Option.some(4));
646         assertThat(of(0, 1, 2, -1, 0, 1, 2).indexWhereOption(i -> i == 1, 3)).isEqualTo(Option.some(5));
647         assertThat(of(0, 1, 2, -1, 0, 1, 2).indexWhereOption(i -> i == 2, 3)).isEqualTo(Option.some(6));
648         assertThat(of(0, 1, 2, -1, 0, 1, 2).indexWhereOption(i -> i == 8, 3)).isEqualTo(Option.none());
649     }
650 
651     @Test(expected = NullPointerException.class)
652     public void shouldFailIndexWhereNullPredicate() {
653         of(1).indexWhere(null);
654     }
655 
656     @Test(expected = NullPointerException.class)
657     public void shouldFailIndexWhereNullPredicateFrom() {
658         of(1).indexWhere(null, 0);
659     }
660 
661     // -- lastIndexWhere
662 
663     @Test
664     public void shouldCalculateLastIndexWhere() {
665         assertThat(of(0, 1, 2, -1, 0, 1, 2).lastIndexWhere(i -> i == 0)).isEqualTo(4);
666         assertThat(of(0, 1, 2, -1, 0, 1, 2).lastIndexWhere(i -> i == 1)).isEqualTo(5);
667         assertThat(of(0, 1, 2, -1, 0, 1, 2).lastIndexWhere(i -> i == 2)).isEqualTo(6);
668         assertThat(of(0, 1, 2, -1, 0, 1, 2).lastIndexWhere(i -> i == 8)).isEqualTo(-1);
669         assertThat(of(0, 1, 2, -1, 0, 1, 2).lastIndexWhere(i -> i == 0, 3)).isEqualTo(0);
670         assertThat(of(0, 1, 2, -1, 0, 1, 2).lastIndexWhere(i -> i == 1, 3)).isEqualTo(1);
671         assertThat(of(0, 1, 2, -1, 0, 1, 2).lastIndexWhere(i -> i == 2, 3)).isEqualTo(2);
672         assertThat(of(0, 1, 2, -1, 0, 1, 2).lastIndexWhere(i -> i == 8, 3)).isEqualTo(-1);
673 
674         assertThat(of(0, 1, 2, -1, 0, 1, 2).lastIndexWhereOption(i -> i == 0)).isEqualTo(Option.some(4));
675         assertThat(of(0, 1, 2, -1, 0, 1, 2).lastIndexWhereOption(i -> i == 1)).isEqualTo(Option.some(5));
676         assertThat(of(0, 1, 2, -1, 0, 1, 2).lastIndexWhereOption(i -> i == 2)).isEqualTo(Option.some(6));
677         assertThat(of(0, 1, 2, -1, 0, 1, 2).lastIndexWhereOption(i -> i == 8)).isEqualTo(Option.none());
678         assertThat(of(0, 1, 2, -1, 0, 1, 2).lastIndexWhereOption(i -> i == 0, 3)).isEqualTo(Option.some(0));
679         assertThat(of(0, 1, 2, -1, 0, 1, 2).lastIndexWhereOption(i -> i == 1, 3)).isEqualTo(Option.some(1));
680         assertThat(of(0, 1, 2, -1, 0, 1, 2).lastIndexWhereOption(i -> i == 2, 3)).isEqualTo(Option.some(2));
681         assertThat(of(0, 1, 2, -1, 0, 1, 2).lastIndexWhereOption(i -> i == 8, 3)).isEqualTo(Option.none());
682     }
683 
684     @Test(expected = NullPointerException.class)
685     public void shouldFailLastIndexWhereNullPredicate() {
686         of(1).lastIndexWhere(null);
687     }
688 
689     @Test(expected = NullPointerException.class)
690     public void shouldFailLastIndexWhereNullPredicateFrom() {
691         of(1).lastIndexWhere(null, 0);
692     }
693 
694     // -- endsWith
695 
696     @Test
697     public void shouldTestEndsWith() {
698         assertThat(empty().endsWith(empty())).isTrue();
699         assertThat(empty().endsWith(of(1))).isFalse();
700         assertThat(of(1, 2, 3, 4).endsWith(empty())).isTrue();
701         assertThat(of(1, 2, 3, 4).endsWith(of(4))).isTrue();
702         assertThat(of(1, 2, 3, 4).endsWith(of(3, 4))).isTrue();
703         assertThat(of(1, 2, 3, 4).endsWith(of(1, 2, 3, 4))).isTrue();
704         assertThat(of(1, 2, 3, 4).endsWith(of(0, 1, 2, 3, 4))).isFalse();
705         assertThat(of(1, 2, 3, 4).endsWith(of(2, 3, 5))).isFalse();
706     }
707 
708     // -- equality
709 
710     @Test
711     public void shouldObeyEqualityConstraints() {
712 
713         // sequential collections
714         assertThat(empty().equals(List.empty())).isTrue();
715         assertThat(of(1).equals(List.of(1))).isTrue();
716         assertThat(of(1, 2, 3).equals(List.of(1, 2, 3))).isTrue();
717         assertThat(of(1, 2, 3).equals(List.of(3, 2, 1))).isFalse();
718 
719         // other classes
720         assertThat(empty().equals(HashMap.empty())).isFalse();
721         assertThat(empty().equals(HashMultimap.withSeq().empty())).isFalse();
722         assertThat(empty().equals(HashSet.empty())).isFalse();
723 
724         assertThat(empty().equals(LinkedHashMap.empty())).isFalse();
725         assertThat(empty().equals(LinkedHashMultimap.withSeq().empty())).isFalse();
726         assertThat(empty().equals(LinkedHashSet.empty())).isFalse();
727 
728         assertThat(empty().equals(TreeMap.empty())).isFalse();
729         assertThat(empty().equals(TreeMultimap.withSeq().empty())).isFalse();
730         assertThat(empty().equals(TreeSet.empty())).isFalse();
731     }
732 
733     // -- insert
734 
735     @Test
736     public void shouldInsertIntoNil() {
737         final Seq<Integer> actual = this.<Integer> empty().insert(0, 1);
738         final Seq<Integer> expected = of(1);
739         assertThat(actual).isEqualTo(expected);
740     }
741 
742     @Test
743     public void shouldInsertInFrontOfElement() {
744         final Seq<Integer> actual = of(4).insert(0, 1);
745         final Seq<Integer> expected = of(1, 4);
746         assertThat(actual).isEqualTo(expected);
747     }
748 
749     @Test
750     public void shouldInsertBehindOfElement() {
751         final Seq<Integer> actual = of(4).insert(1, 5);
752         final Seq<Integer> expected = of(4, 5);
753         assertThat(actual).isEqualTo(expected);
754     }
755 
756     @Test
757     public void shouldInsertIntoSeq() {
758         final Seq<Integer> actual = of(1, 2, 3).insert(2, 4);
759         final Seq<Integer> expected = of(1, 2, 4, 3);
760         assertThat(actual).isEqualTo(expected);
761     }
762 
763     @Test(expected = IndexOutOfBoundsException.class)
764     public void shouldThrowWhenInsertOnNonNilWithNegativeIndex() {
765         of(1).insert(-1, null);
766     }
767 
768     @Test(expected = IndexOutOfBoundsException.class)
769     public void shouldThrowWhenInsertOnNilWithNegativeIndex() {
770         empty().insert(-1, null);
771     }
772 
773     @Test(expected = IndexOutOfBoundsException.class)
774     public void shouldThrowOnInsertWhenExceedingUpperBound() {
775         empty().insert(1, null);
776     }
777 
778     // -- insertAll
779 
780     @Test
781     public void shouldInsertAllIntoNil() {
782         final Seq<Integer> actual = this.<Integer> empty().insertAll(0, of(1, 2, 3));
783         final Seq<Integer> expected = of(1, 2, 3);
784         assertThat(actual).isEqualTo(expected);
785     }
786 
787     @Test
788     public void shouldInsertAllInFrontOfElement() {
789         final Seq<Integer> actual = of(4).insertAll(0, of(1, 2, 3));
790         final Seq<Integer> expected = of(1, 2, 3, 4);
791         assertThat(actual).isEqualTo(expected);
792     }
793 
794     @Test
795     public void shouldInsertAllBehindOfElement() {
796         final Seq<Integer> actual = of(4).insertAll(1, of(1, 2, 3));
797         final Seq<Integer> expected = of(4, 1, 2, 3);
798         assertThat(actual).isEqualTo(expected);
799     }
800 
801     @Test
802     public void shouldInsertAllIntoSeq() {
803         final Seq<Integer> actual = of(1, 2, 3).insertAll(2, of(4, 5));
804         final Seq<Integer> expected = of(1, 2, 4, 5, 3);
805         assertThat(actual).isEqualTo(expected);
806     }
807 
808     @Test(expected = NullPointerException.class)
809     public void shouldThrowOnInsertAllWithNil() {
810         empty().insertAll(0, null);
811     }
812 
813     @Test(expected = IndexOutOfBoundsException.class)
814     public void shouldThrowWhenInsertOnNonNilAllWithNegativeIndex() {
815         of(1).insertAll(-1, empty());
816     }
817 
818     @Test(expected = IndexOutOfBoundsException.class)
819     public void shouldThrowWhenInsertOnNilAllWithNegativeIndex() {
820         empty().insertAll(-1, empty());
821     }
822 
823     @Test(expected = IndexOutOfBoundsException.class)
824     public void shouldThrowOnInsertAllWhenExceedingUpperBound() {
825         empty().insertAll(1, empty());
826     }
827 
828     @Test
829     public void shouldReturnSameSeqWhenEmptyInsertAllEmpty() {
830         final Seq<Integer> empty = empty();
831         assertThat(empty.insertAll(0, empty())).isSameAs(empty);
832     }
833 
834     @Test
835     public void shouldReturnSameSeqWhenEmptyInsertAllNonEmpty() {
836         final Seq<Integer> seq = of(1, 2, 3);
837         assertThat(empty().insertAll(0, seq)).isSameAs(seq);
838     }
839 
840     @Test
841     public void shouldReturnSameSeqWhenNonEmptyInsertAllEmpty() {
842         final Seq<Integer> seq = of(1, 2, 3);
843         assertThat(seq.insertAll(0, empty())).isSameAs(seq);
844     }
845 
846     // -- intersperse
847 
848     @Test
849     public void shouldIntersperseNil() {
850         assertThat(this.<Character> empty().intersperse(',')).isEmpty();
851     }
852 
853     @Test
854     public void shouldIntersperseSingleton() {
855         assertThat(of('a').intersperse(',')).isEqualTo(of('a'));
856     }
857 
858     @Test
859     public void shouldIntersperseMultipleElements() {
860         assertThat(of('a', 'b').intersperse(',')).isEqualTo(of('a', ',', 'b'));
861     }
862 
863     // -- iterator(int)
864 
865     @Test(expected = IndexOutOfBoundsException.class)
866     public void shouldThrowWhenNilIteratorStartingAtIndex() {
867         empty().iterator(1);
868     }
869 
870     @Test
871     public void shouldIterateFirstElementOfNonNilStartingAtIndex() {
872         assertThat(of(1, 2, 3).iterator(1).next()).isEqualTo(2);
873     }
874 
875     @Test
876     public void shouldFullyIterateNonNilStartingAtIndex() {
877         int actual = -1;
878         for (Iterator<Integer> iter = of(1, 2, 3).iterator(1); iter.hasNext(); ) {
879             actual = iter.next();
880         }
881         assertThat(actual).isEqualTo(3);
882     }
883 
884     // -- padTo
885 
886     @Test
887     public void shouldPadEmptyToEmpty() {
888         assertThat(empty().padTo(0, 1)).isSameAs(empty());
889     }
890 
891     @Test
892     public void shouldPadEmptyToNonEmpty() {
893         assertThat(empty().padTo(2, 1)).isEqualTo(of(1, 1));
894     }
895 
896     @Test
897     public void shouldPadNonEmptyZeroLen() {
898         final Seq<Integer> seq = of(1);
899         assertThat(seq.padTo(0, 2)).isSameAs(seq);
900     }
901 
902     @Test
903     public void shouldPadNonEmpty() {
904         assertThat(of(1).padTo(2, 1)).isEqualTo(of(1, 1));
905         assertThat(of(1).padTo(2, 2)).isEqualTo(of(1, 2));
906         assertThat(of(1).padTo(3, 2)).isEqualTo(of(1, 2, 2));
907     }
908 
909     // -- leftPadTo
910 
911     @Test
912     public void shouldLeftPadEmptyToEmpty() {
913         assertThat(empty().leftPadTo(0, 1)).isSameAs(empty());
914     }
915 
916     @Test
917     public void shouldLeftPadEmptyToNonEmpty() {
918         assertThat(empty().leftPadTo(2, 1)).isEqualTo(of(1, 1));
919     }
920 
921     @Test
922     public void shouldLeftPadNonEmptyZeroLen() {
923         final Seq<Integer> seq = of(1);
924         assertThat(seq.leftPadTo(0, 2)).isSameAs(seq);
925     }
926 
927     @Test
928     public void shouldLeftPadNonEmpty() {
929         assertThat(of(1).leftPadTo(2, 1)).isEqualTo(of(1, 1));
930         assertThat(of(1).leftPadTo(2, 2)).isEqualTo(of(2, 1));
931         assertThat(of(1).leftPadTo(3, 2)).isEqualTo(of(2, 2, 1));
932     }
933 
934     // -- patch
935 
936     @Test
937     public void shouldPatchEmptyByEmpty() {
938         assertThat(empty().patch(0, empty(), 0)).isEmpty();
939         assertThat(empty().patch(-1, empty(), -1)).isEmpty();
940         assertThat(empty().patch(-1, empty(), 1)).isEmpty();
941         assertThat(empty().patch(1, empty(), -1)).isEmpty();
942         assertThat(empty().patch(1, empty(), 1)).isEmpty();
943     }
944 
945     @Test
946     public void shouldPatchEmptyByNonEmpty() {
947         final Seq<Character> s = of('1', '2', '3');
948         assertThat(empty().patch(0, s, 0)).isEqualTo(s);
949         assertThat(empty().patch(-1, s, -1)).isEqualTo(s);
950         assertThat(empty().patch(-1, s, 1)).isEqualTo(s);
951         assertThat(empty().patch(1, s, -1)).isEqualTo(s);
952         assertThat(empty().patch(1, s, 1)).isEqualTo(s);
953     }
954 
955     @Test
956     public void shouldPatchNonEmptyByEmpty() {
957         final Seq<Character> s = of('1', '2', '3');
958         assertThat(s.patch(-1, empty(), -1)).isEqualTo(of('1', '2', '3'));
959         assertThat(s.patch(-1, empty(), 0)).isEqualTo(of('1', '2', '3'));
960         assertThat(s.patch(-1, empty(), 1)).isEqualTo(of('2', '3'));
961         assertThat(s.patch(-1, empty(), 3)).isEmpty();
962         assertThat(s.patch(0, empty(), -1)).isEqualTo(of('1', '2', '3'));
963         assertThat(s.patch(0, empty(), 0)).isEqualTo(of('1', '2', '3'));
964         assertThat(s.patch(0, empty(), 1)).isEqualTo(of('2', '3'));
965         assertThat(s.patch(0, empty(), 3)).isEmpty();
966         assertThat(s.patch(1, empty(), -1)).isEqualTo(of('1', '2', '3'));
967         assertThat(s.patch(1, empty(), 0)).isEqualTo(of('1', '2', '3'));
968         assertThat(s.patch(1, empty(), 1)).isEqualTo(of('1', '3'));
969         assertThat(s.patch(1, empty(), 3)).isEqualTo(of('1'));
970         assertThat(s.patch(4, empty(), -1)).isEqualTo(of('1', '2', '3'));
971         assertThat(s.patch(4, empty(), 0)).isEqualTo(of('1', '2', '3'));
972         assertThat(s.patch(4, empty(), 1)).isEqualTo(of('1', '2', '3'));
973         assertThat(s.patch(4, empty(), 3)).isEqualTo(of('1', '2', '3'));
974     }
975 
976     @Test
977     public void shouldPatchNonEmptyByNonEmpty() {
978         final Seq<Character> s = of('1', '2', '3');
979         final Seq<Character> d = of('4', '5', '6');
980         assertThat(s.patch(-1, d, -1)).isEqualTo(of('4', '5', '6', '1', '2', '3'));
981         assertThat(s.patch(-1, d, 0)).isEqualTo(of('4', '5', '6', '1', '2', '3'));
982         assertThat(s.patch(-1, d, 1)).isEqualTo(of('4', '5', '6', '2', '3'));
983         assertThat(s.patch(-1, d, 3)).isEqualTo(of('4', '5', '6'));
984         assertThat(s.patch(0, d, -1)).isEqualTo(of('4', '5', '6', '1', '2', '3'));
985         assertThat(s.patch(0, d, 0)).isEqualTo(of('4', '5', '6', '1', '2', '3'));
986         assertThat(s.patch(0, d, 1)).isEqualTo(of('4', '5', '6', '2', '3'));
987         assertThat(s.patch(0, d, 3)).isEqualTo(of('4', '5', '6'));
988         assertThat(s.patch(1, d, -1)).isEqualTo(of('1', '4', '5', '6', '2', '3'));
989         assertThat(s.patch(1, d, 0)).isEqualTo(of('1', '4', '5', '6', '2', '3'));
990         assertThat(s.patch(1, d, 1)).isEqualTo(of('1', '4', '5', '6', '3'));
991         assertThat(s.patch(1, d, 3)).isEqualTo(of('1', '4', '5', '6'));
992         assertThat(s.patch(4, d, -1)).isEqualTo(of('1', '2', '3', '4', '5', '6'));
993         assertThat(s.patch(4, d, 0)).isEqualTo(of('1', '2', '3', '4', '5', '6'));
994         assertThat(s.patch(4, d, 1)).isEqualTo(of('1', '2', '3', '4', '5', '6'));
995         assertThat(s.patch(4, d, 3)).isEqualTo(of('1', '2', '3', '4', '5', '6'));
996     }
997 
998     // -- permutations
999 
1000     @Test
1001     public void shouldComputePermutationsOfEmptySeq() {
1002         assertThat(empty().permutations()).isEmpty();
1003     }
1004 
1005     @SuppressWarnings("unchecked")
1006     @Test
1007     public void shouldComputePermutationsOfNonEmptySeq() {
1008         assertThat(of(1, 2, 3).permutations())
1009                 .isEqualTo(ofAll(of(of(1, 2, 3), of(1, 3, 2), of(2, 1, 3), of(2, 3, 1), of(3, 1, 2), of(3, 2, 1))));
1010     }
1011 
1012     // -- map
1013 
1014     @Test
1015     public void shouldMapTransformedSeq() {
1016         final Function<Integer, Integer> mapper = o -> o + 1;
1017         assertThat(this.<Integer> empty().map(mapper)).isEmpty();
1018         assertThat(of(3, 1, 4, 1, 5).map(mapper)).isEqualTo(of(4, 2, 5, 2, 6));
1019         assertThat(of(3, 1, 4, 1, 5, 9, 2).sorted().distinct().drop(1).init().remove(5).map(mapper).tail()).isEqualTo(of(4, 5));
1020     }
1021 
1022     // -- prefixLength
1023 
1024     @Test
1025     public void shouldCalculatePrefixLength() {
1026         assertThat(of(1, 3, 5, 6).prefixLength(i -> (i & 1) > 0)).isEqualTo(3);
1027         assertThat(of(1, 3, 5).prefixLength(i -> (i & 1) > 0)).isEqualTo(3);
1028         assertThat(of(2).prefixLength(i -> (i & 1) > 0)).isEqualTo(0);
1029         assertThat(empty().prefixLength(i -> true)).isEqualTo(0);
1030     }
1031 
1032     @Test(expected = NullPointerException.class)
1033     public void shouldThrowPrefixLengthNullPredicate() {
1034         of(1).prefixLength(null);
1035     }
1036 
1037     // -- segmentLength
1038 
1039     @Test
1040     public void shouldCalculateSegmentLength() {
1041         assertThat(of(1, 3, 5, 6).segmentLength(i -> (i & 1) > 0, 1)).isEqualTo(2);
1042         assertThat(of(1, 3, 5).segmentLength(i -> (i & 1) > 0, 1)).isEqualTo(2);
1043         assertThat(of(2, 2).segmentLength(i -> (i & 1) > 0, 1)).isEqualTo(0);
1044         assertThat(of(2).segmentLength(i -> (i & 1) > 0, 1)).isEqualTo(0);
1045         assertThat(empty().segmentLength(i -> true, 1)).isEqualTo(0);
1046     }
1047 
1048     @Test(expected = NullPointerException.class)
1049     public void shouldThrowSegmentLengthNullPredicate() {
1050         of(1).segmentLength(null, 0);
1051     }
1052 
1053     // -- prepend
1054 
1055     @Test
1056     public void shouldPrependElementToNil() {
1057         final Seq<Integer> actual = this.<Integer> empty().prepend(1);
1058         final Seq<Integer> expected = of(1);
1059         assertThat(actual).isEqualTo(expected);
1060     }
1061 
1062     @Test
1063     public void shouldPrependElementToNonNil() {
1064         final Seq<Integer> actual = of(2, 3).prepend(1);
1065         final Seq<Integer> expected = of(1, 2, 3);
1066         assertThat(actual).isEqualTo(expected);
1067     }
1068 
1069     // -- prependAll
1070 
1071     @Test(expected = NullPointerException.class)
1072     public void shouldThrowOnPrependAllOfNull() {
1073         empty().prependAll(null);
1074     }
1075 
1076     @Test
1077     public void shouldPrependAllNilToNil() {
1078         final Seq<Integer> actual = this.<Integer> empty().prependAll(empty());
1079         final Seq<Integer> expected = empty();
1080         assertThat(actual).isEqualTo(expected);
1081     }
1082 
1083     @Test
1084     public void shouldPrependAllNilToNonNil() {
1085         final Seq<Integer> actual = of(1, 2, 3).prependAll(empty());
1086         final Seq<Integer> expected = of(1, 2, 3);
1087         assertThat(actual).isEqualTo(expected);
1088     }
1089 
1090     @Test
1091     public void shouldPrependAllNonNilToNil() {
1092         final Seq<Integer> actual = this.<Integer> empty().prependAll(of(1, 2, 3));
1093         final Seq<Integer> expected = of(1, 2, 3);
1094         assertThat(actual).isEqualTo(expected);
1095     }
1096 
1097     @Test
1098     public void shouldPrependAllNonNilToNonNil() {
1099         final Seq<Integer> expected = range(0, 100);
1100 
1101         final Seq<Integer> actualFirstPartLarger = range(90, 100).prependAll(range(0, 90));
1102         assertThat(actualFirstPartLarger).isEqualTo(expected);
1103 
1104         final Seq<Integer> actualSecondPartLarger = range(10, 100).prependAll(range(0, 10));
1105         assertThat(actualSecondPartLarger).isEqualTo(expected);
1106     }
1107 
1108     @Test
1109     public void shouldReturnSameSeqWhenEmptyPrependAllEmpty() {
1110         final Seq<Integer> empty = empty();
1111         assertThat(empty.prependAll(empty())).isSameAs(empty);
1112     }
1113 
1114     @Test
1115     public void shouldReturnSameSeqWhenEmptyPrependAllNonEmpty() {
1116         final Seq<Integer> seq = of(1, 2, 3);
1117         assertThat(empty().prependAll(seq)).isSameAs(seq);
1118     }
1119 
1120     @Test
1121     public void shouldReturnSameSeqWhenNonEmptyPrependAllEmpty() {
1122         final Seq<Integer> seq = of(1, 2, 3);
1123         assertThat(seq.prependAll(empty())).isSameAs(seq);
1124     }
1125 
1126     // -- remove
1127 
1128     @Test
1129     public void shouldRemoveElementFromNil() {
1130         assertThat(empty().remove(null)).isEmpty();
1131     }
1132 
1133     @Test
1134     public void shouldRemoveFirstElement() {
1135         assertThat(of(1, 2, 3).remove(1)).isEqualTo(of(2, 3));
1136     }
1137 
1138     @Test
1139     public void shouldRemoveLastElement() {
1140         assertThat(of(1, 2, 3).remove(3)).isEqualTo(of(1, 2));
1141     }
1142 
1143     @Test
1144     public void shouldRemoveInnerElement() {
1145         assertThat(of(1, 2, 3).remove(2)).isEqualTo(of(1, 3));
1146     }
1147 
1148     @Test
1149     public void shouldNotRemoveDuplicateElement() {
1150         assertThat(of(1, 2, 3, 1, 2).remove(1).remove(3)).isEqualTo(of(2, 1, 2));
1151     }
1152 
1153     @Test
1154     public void shouldRemoveNonExistingElement() {
1155         final Seq<Integer> t = of(1, 2, 3);
1156         if (useIsEqualToInsteadOfIsSameAs()) {
1157             assertThat(t.remove(4)).isEqualTo(t);
1158         } else {
1159             assertThat(t.remove(4)).isSameAs(t);
1160         }
1161     }
1162 
1163     // -- removeFirst(Predicate)
1164 
1165     @Test
1166     public void shouldRemoveFirstElementByPredicateFromNil() {
1167         assertThat(empty().removeFirst(v -> true)).isEmpty();
1168     }
1169 
1170     @Test
1171     public void shouldRemoveFirstElementByPredicateBegin() {
1172         assertThat(of(1, 2, 3).removeFirst(v -> v == 1)).isEqualTo(of(2, 3));
1173     }
1174 
1175     @Test
1176     public void shouldRemoveFirstElementByPredicateBeginM() {
1177         assertThat(of(1, 2, 1, 3).removeFirst(v -> v == 1)).isEqualTo(of(2, 1, 3));
1178     }
1179 
1180     @Test
1181     public void shouldRemoveFirstElementByPredicateEnd() {
1182         assertThat(of(1, 2, 3).removeFirst(v -> v == 3)).isEqualTo(of(1, 2));
1183     }
1184 
1185     @Test
1186     public void shouldRemoveFirstElementByPredicateInner() {
1187         assertThat(of(1, 2, 3, 4, 5).removeFirst(v -> v == 3)).isEqualTo(of(1, 2, 4, 5));
1188     }
1189 
1190     @Test
1191     public void shouldRemoveFirstElementByPredicateInnerM() {
1192         assertThat(of(1, 2, 3, 2, 5).removeFirst(v -> v == 2)).isEqualTo(of(1, 3, 2, 5));
1193     }
1194 
1195     @Test
1196     public void shouldRemoveFirstElementByPredicateNonExisting() {
1197         final Seq<Integer> t = of(1, 2, 3);
1198         if (useIsEqualToInsteadOfIsSameAs()) {
1199             assertThat(t.removeFirst(v -> v == 4)).isEqualTo(t);
1200         } else {
1201             assertThat(t.removeFirst(v -> v == 4)).isSameAs(t);
1202         }
1203     }
1204 
1205     // -- removeLast(Predicate)
1206 
1207     @Test
1208     public void shouldRemoveLastElementByPredicateFromNil() {
1209         assertThat(empty().removeLast(v -> true)).isEmpty();
1210     }
1211 
1212     @Test
1213     public void shouldRemoveLastElementByPredicateBegin() {
1214         assertThat(of(1, 2, 3).removeLast(v -> v == 1)).isEqualTo(of(2, 3));
1215     }
1216 
1217     @Test
1218     public void shouldRemoveLastElementByPredicateEnd() {
1219         assertThat(of(1, 2, 3).removeLast(v -> v == 3)).isEqualTo(of(1, 2));
1220     }
1221 
1222     @Test
1223     public void shouldRemoveLastElementByPredicateEndM() {
1224         assertThat(of(1, 3, 2, 3).removeLast(v -> v == 3)).isEqualTo(of(1, 3, 2));
1225     }
1226 
1227     @Test
1228     public void shouldRemoveLastElementByPredicateInner() {
1229         assertThat(of(1, 2, 3, 4, 5).removeLast(v -> v == 3)).isEqualTo(of(1, 2, 4, 5));
1230     }
1231 
1232     @Test
1233     public void shouldRemoveLastElementByPredicateInnerM() {
1234         assertThat(of(1, 2, 3, 2, 5).removeLast(v -> v == 2)).isEqualTo(of(1, 2, 3, 5));
1235     }
1236 
1237     @Test
1238     public void shouldRemoveLastElementByPredicateNonExisting() {
1239         final Seq<Integer> t = of(1, 2, 3);
1240         if (useIsEqualToInsteadOfIsSameAs()) {
1241             assertThat(t.removeLast(v -> v == 4)).isEqualTo(t);
1242         } else {
1243             assertThat(t.removeLast(v -> v == 4)).isSameAs(t);
1244         }
1245     }
1246 
1247     // -- removeAll(Iterable)
1248 
1249     @Test
1250     public void shouldRemoveAllElementsFromNil() {
1251         assertThat(empty().removeAll(of(1, 2, 3))).isEmpty();
1252     }
1253 
1254     @Test
1255     public void shouldRemoveAllExistingElementsFromNonNil() {
1256         assertThat(of(1, 2, 3, 1, 2, 3).removeAll(of(1, 2))).isEqualTo(of(3, 3));
1257     }
1258 
1259     @Test
1260     public void shouldNotRemoveAllNonExistingElementsFromNonNil() {
1261         final Seq<Integer> t = of(1, 2, 3);
1262         if (useIsEqualToInsteadOfIsSameAs()) {
1263             assertThat(t.removeAll(of(4, 5))).isEqualTo(t);
1264         } else {
1265             assertThat(t.removeAll(of(4, 5))).isSameAs(t);
1266         }
1267     }
1268 
1269     @Test
1270     public void shouldReturnSameSeqWhenNonEmptyRemoveAllEmpty() {
1271         final Seq<Integer> seq = of(1, 2, 3);
1272         assertThat(seq.removeAll(empty())).isSameAs(seq);
1273     }
1274 
1275     @Test
1276     public void shouldReturnSameSeqWhenEmptyRemoveAllNonEmpty() {
1277         final Seq<Integer> empty = empty();
1278         assertThat(empty.removeAll(of(1, 2, 3))).isSameAs(empty);
1279     }
1280 
1281     // -- removeAll(Predicate)
1282 
1283     @Test
1284     public void shouldRemoveExistingElements() {
1285         assertThat(of(1, 2, 3).removeAll(i -> i == 1)).isEqualTo(of(2, 3));
1286         assertThat(of(1, 2, 3).removeAll(i -> i == 2)).isEqualTo(of(1, 3));
1287         assertThat(of(1, 2, 3).removeAll(i -> i == 3)).isEqualTo(of(1, 2));
1288         if (useIsEqualToInsteadOfIsSameAs()) {
1289             assertThat(of(1, 2, 3).removeAll(ignore -> true)).isEmpty();
1290             assertThat(of(1, 2, 3).removeAll(ignore -> false)).isEqualTo(of(1, 2, 3));
1291         } else {
1292             final Seq<Integer> seq = of(1, 2, 3);
1293             assertThat(seq.removeAll(ignore -> false)).isSameAs(seq);
1294         }
1295     }
1296 
1297     @Test
1298     public void shouldRemoveNonExistingElements() {
1299         if (useIsEqualToInsteadOfIsSameAs()) {
1300             assertThat(this.<Integer> empty().removeAll(i -> i == 0)).isEqualTo(empty());
1301             assertThat(of(1, 2, 3).removeAll(i -> i != 0)).isEqualTo(empty());
1302         } else {
1303             assertThat(this.<Integer> empty().removeAll(i -> i == 0)).isSameAs(empty());
1304             assertThat(of(1, 2, 3).removeAll(i -> i != 0)).isSameAs(empty());
1305         }
1306     }
1307 
1308     @Test
1309     public void shouldRemoveAllElementsByPredicateFromNil() {
1310         assertThat(empty().removeAll(o -> true)).isEmpty();
1311     }
1312 
1313     @Test
1314     public void shouldRemoveAllExistingElements() {
1315         assertThat(of(1, 2, 3, 4, 5, 6).removeAll(ignored -> true)).isEmpty();
1316     }
1317 
1318     @Test
1319     public void shouldRemoveAllMatchedElementsFromNonNil() {
1320         assertThat(of(1, 2, 3, 4, 5, 6).removeAll(i -> i % 2 == 0)).isEqualTo(of(1, 3, 5));
1321     }
1322 
1323     @Test
1324     public void shouldNotRemoveAllNonMatchedElementsFromNonNil() {
1325         final Seq<Integer> t = of(1, 2, 3);
1326         final Predicate<Integer> isTooBig = i -> i >= 4;
1327         if (useIsEqualToInsteadOfIsSameAs()) {
1328             assertThat(t.removeAll(isTooBig)).isEqualTo(t);
1329         } else {
1330             assertThat(t.removeAll(isTooBig)).isSameAs(t);
1331         }
1332     }
1333 
1334     // -- removeAll(Object)
1335 
1336     @Test
1337     public void shouldRemoveAllObjectsFromNil() {
1338         assertThat(empty().removeAll(1)).isEmpty();
1339     }
1340 
1341     @Test
1342     public void shouldRemoveAllExistingObjectsFromNonNil() {
1343         assertThat(of(1, 2, 3, 1, 2, 3).removeAll(1)).isEqualTo(of(2, 3, 2, 3));
1344     }
1345 
1346     @Test
1347     public void shouldNotRemoveAllNonObjectsElementsFromNonNil() {
1348         final Seq<Integer> seq = of(1, 2, 3);
1349         if (useIsEqualToInsteadOfIsSameAs()) {
1350             assertThat(seq.removeAll(4)).isEqualTo(seq);
1351         } else {
1352             assertThat(seq.removeAll(4)).isSameAs(seq);
1353         }
1354     }
1355 
1356     @Test
1357     public void shouldRemoveAllNullsFromNonEmpty() {
1358         final Seq<Integer> seq = of(1, null, 2, null, 3);
1359         assertThat(seq.removeAll((Integer) null)).isEqualTo(of(1, 2, 3));
1360     }
1361 
1362     // -- removeAt(index)
1363 
1364     @Test(expected = IndexOutOfBoundsException.class)
1365     public void shouldRemoveIndexAtNil() {
1366         assertThat(empty().removeAt(1)).isEmpty();
1367     }
1368 
1369     @Test
1370     public void shouldRemoveIndexAtNonNil() {
1371         assertThat(of(1, 2, 3).removeAt(1)).isEqualTo(of(1, 3));
1372     }
1373 
1374     @Test
1375     public void shouldRemoveIndexAtBegin() {
1376         assertThat(of(1, 2, 3).removeAt(0)).isEqualTo(of(2, 3));
1377     }
1378 
1379     @Test
1380     public void shouldRemoveIndexAtEnd() {
1381         assertThat(of(1, 2, 3).removeAt(2)).isEqualTo(of(1, 2));
1382     }
1383 
1384     @Test
1385     public void shouldRemoveMultipleTimes() {
1386         assertThat(of(3, 1, 4, 1, 5, 9, 2).removeAt(0).removeAt(0).removeAt(4).removeAt(3).removeAt(1)).isEqualTo(of(4, 5));
1387     }
1388 
1389     @Test(expected = IndexOutOfBoundsException.class)
1390     public void shouldRemoveIndexOutOfBoundsLeft() {
1391         assertThat(of(1, 2, 3).removeAt(-1)).isEqualTo(of(1, 2, 3));
1392     }
1393 
1394     @Test(expected = IndexOutOfBoundsException.class)
1395     public void shouldRemoveIndexOutOfBoundsRight() {
1396         assertThat(of(1, 2, 3).removeAt(5)).isEqualTo(of(1, 2, 3));
1397     }
1398 
1399     // -- reverse
1400 
1401     @Test
1402     public void shouldReverseNil() {
1403         assertThat(empty().reverse()).isEmpty();
1404     }
1405 
1406     @Test
1407     public void shouldReverseNonNil() {
1408         assertThat(of(1, 2, 3).reverse()).isEqualTo(of(3, 2, 1));
1409     }
1410 
1411     // -- reverseIterator
1412 
1413     @Test
1414     public void shouldCreateReverseIteratorOfEmpty() {
1415         assertThat(ofAll(empty()).reverseIterator()).isEmpty();
1416     }
1417 
1418     @Test
1419     public void shouldCreateReverseIteratorOfSingle() {
1420         assertThat(ofAll(this.of("a")).reverseIterator().toList()).isEqualTo(Iterator.of("a").toList());
1421     }
1422 
1423     @Test
1424     public void shouldCreateReverseIteratorOfNonEmpty() {
1425         assertThat(ofAll(of("a", "b", "c")).reverseIterator().toList()).isEqualTo(Iterator.of("c", "b", "a").toList());
1426     }
1427 
1428     // -- shuffle
1429 
1430     @Test
1431     public void shouldShuffleEmpty() {
1432         assertThat(empty().shuffle().isEmpty());
1433     }
1434 
1435     @Test
1436     public void shouldShuffleHaveSameLength() {
1437         assertThat(of(1, 2, 3).shuffle().size()).isEqualTo(of(1, 2, 3).size());
1438     }
1439 
1440     @Test
1441     public void shouldShuffleHaveSameElements() {
1442         final Seq<Integer> shuffled = of(1, 2, 3).shuffle();
1443         assertThat(shuffled.indexOf(1)).isNotEqualTo(-1);
1444         assertThat(shuffled.indexOf(2)).isNotEqualTo(-1);
1445         assertThat(shuffled.indexOf(3)).isNotEqualTo(-1);
1446         assertThat(shuffled.indexOf(4)).isEqualTo(-1);
1447     }
1448 
1449     // -- update
1450 
1451     @Test(expected = IndexOutOfBoundsException.class)
1452     public void shouldThrowWhenUpdatedWithNegativeIndexOnNil() {
1453         empty().update(-1, (Integer) null);
1454     }
1455 
1456     @Test(expected = IndexOutOfBoundsException.class)
1457     public void shouldThrowWhenUpdatedWithNegativeIndexOnNonNil() {
1458         of(1).update(-1, 2);
1459     }
1460 
1461     @Test(expected = IndexOutOfBoundsException.class)
1462     public void shouldThrowWhenUpdatedOnNil() {
1463         empty().update(0, (Integer) null);
1464     }
1465 
1466     @Test(expected = IndexOutOfBoundsException.class)
1467     public void shouldThrowWhenUpdatedWithIndexExceedingByOneOnNonNil() {
1468         of(1).update(1, 2);
1469     }
1470 
1471     @Test(expected = IndexOutOfBoundsException.class)
1472     public void shouldThrowWhenUpdatedWithIndexExceedingByTwoOnNonNil() {
1473         of(1).update(2, 2);
1474     }
1475 
1476     @Test
1477     public void shouldUpdateFirstElement() {
1478         assertThat(of(1, 2, 3).update(0, 4)).isEqualTo(of(4, 2, 3));
1479     }
1480 
1481     @Test
1482     public void shouldUpdateLastElement() {
1483         assertThat(of(1, 2, 3).update(2, 4)).isEqualTo(of(1, 2, 4));
1484     }
1485 
1486 
1487     // -- higher order update
1488 
1489     @Test
1490     public void shouldUpdateViaFunction() throws Exception {
1491         final Seq<Character> actual = ofAll("hello".toCharArray()).update(0, Character::toUpperCase);
1492         final Seq<Character> expected = ofAll("Hello".toCharArray());
1493         assertThat(actual).isEqualTo(expected);
1494     }
1495 
1496     // -- slice(beginIndex, endIndex)
1497 
1498     @Test
1499     public void shouldReturnNilWhenSliceFrom0To0OnNil() {
1500         final Seq<Integer> actual = this.<Integer> empty().slice(0, 0);
1501         assertThat(actual).isEmpty();
1502     }
1503 
1504     @Test
1505     public void shouldReturnNilWhenSliceFrom0To0OnNonNil() {
1506         final Seq<Integer> actual = of(1).slice(0, 0);
1507         assertThat(actual).isEmpty();
1508     }
1509 
1510     @Test
1511     public void shouldReturnSeqWithFirstElementWhenSliceFrom0To1OnNonNil() {
1512         final Seq<Integer> actual = of(1).slice(0, 1);
1513         assertThat(actual).isEqualTo(of(1));
1514     }
1515 
1516     @Test
1517     public void shouldReturnNilWhenSliceFrom1To1OnNonNil() {
1518         final Seq<Integer> actual = of(1).slice(1, 1);
1519         assertThat(actual).isEmpty();
1520     }
1521 
1522     @Test
1523     public void shouldReturnSliceWhenIndicesAreWithinRange() {
1524         final Seq<Integer> actual = of(1, 2, 3).slice(1, 3);
1525         assertThat(actual).isEqualTo(of(2, 3));
1526     }
1527 
1528     @Test
1529     public void shouldReturnNilOnSliceWhenIndicesBothAreUpperBound() {
1530         final Seq<Integer> actual = of(1, 2, 3).slice(3, 3);
1531         assertThat(actual).isEmpty();
1532     }
1533 
1534     @Test
1535     public void shouldComputeSliceOnNonNilWhenBeginIndexIsGreaterThanEndIndex() {
1536         assertThat(of(1, 2, 3).slice(1, 0)).isEmpty();
1537     }
1538 
1539     @Test
1540     public void shouldComputeSliceOnNilWhenBeginIndexIsGreaterThanEndIndex() {
1541         assertThat(empty().slice(1, 0)).isEmpty();
1542     }
1543 
1544     @Test
1545     public void shouldComputeSliceOnNonNilWhenBeginIndexExceedsLowerBound() {
1546         assertThat(of(1, 2, 3).slice(-1, 2)).isEqualTo(of(1, 2));
1547     }
1548 
1549     @Test
1550     public void shouldComputeSliceOnNilWhenBeginIndexExceedsLowerBound() {
1551         assertThat(empty().slice(-1, 2)).isEmpty();
1552     }
1553 
1554     @Test
1555     public void shouldThrowWhenSlice2OnNil() {
1556         assertThat(empty().slice(0, 1)).isEmpty();
1557     }
1558 
1559     @Test
1560     public void shouldComputeSliceWhenEndIndexExceedsUpperBound() {
1561         assertThat(of(1, 2, 3).slice(1, 4)).isEqualTo(of(2, 3));
1562     }
1563 
1564     @Test
1565     public void shouldComputeSliceWhenBeginIndexIsGreaterThanEndIndex() {
1566         assertThat(of(1, 2, 3).slice(2, 1)).isEmpty();
1567     }
1568 
1569     @Test
1570     public void shouldComputeSliceWhenBeginIndexAndEndIndexAreBothOutOfBounds() {
1571         assertThat(of(1, 2, 3).slice(-10, 10)).isEqualTo(of(1, 2, 3));
1572     }
1573 
1574     // -- sorted()
1575 
1576     @Test
1577     public void shouldSortNil() {
1578         assertThat(empty().sorted()).isEmpty();
1579     }
1580 
1581     @Test
1582     public void shouldSortNonNil() {
1583         assertThat(of(3, 4, 1, 2).sorted()).isEqualTo(of(1, 2, 3, 4));
1584     }
1585 
1586     // -- sorted(Comparator)
1587 
1588     @Test
1589     public void shouldSortNilUsingComparator() {
1590         assertThat(this.<Integer> empty().sorted((i, j) -> j - i)).isEmpty();
1591     }
1592 
1593     @Test
1594     public void shouldSortNonNilUsingComparator() {
1595         assertThat(of(3, 4, 1, 2).sorted((i, j) -> j - i)).isEqualTo(of(4, 3, 2, 1));
1596     }
1597 
1598     // -- sortBy(Function)
1599 
1600     @Test
1601     public void shouldSortByNilUsingFunction() {
1602         assertThat(this.<String> empty().sortBy(String::length)).isEmpty();
1603     }
1604 
1605     @Test
1606     public void shouldSortByNonNilUsingFunction() {
1607         final Seq<String> testee = of("aaa", "b", "cc");
1608         final Seq<String> actual = testee.sortBy(String::length);
1609         final Seq<String> expected = of("b", "cc", "aaa");
1610         assertThat(actual).isEqualTo(expected);
1611     }
1612 
1613     // -- sortBy(Comparator, Function)
1614 
1615     @Test
1616     public void shouldSortByNilUsingComparatorAndFunction() {
1617         assertThat(this.<String> empty().sortBy(String::length)).isEmpty();
1618     }
1619 
1620     @Test
1621     public void shouldSortByNonNilUsingComparatorAndFunction() {
1622         final Seq<String> testee = of("aaa", "b", "cc");
1623         final Seq<String> actual = testee.sortBy((i1, i2) -> i2 - i1, String::length);
1624         final Seq<String> expected = of("aaa", "cc", "b");
1625         assertThat(actual).isEqualTo(expected);
1626     }
1627 
1628     // -- splitAt(index)
1629 
1630     @Test
1631     public void shouldSplitAtNil() {
1632         assertThat(empty().splitAt(1)).isEqualTo(Tuple.of(empty(), empty()));
1633     }
1634 
1635     @Test
1636     public void shouldSplitAtNonNil() {
1637         assertThat(of(1, 2, 3).splitAt(1)).isEqualTo(Tuple.of(of(1), of(2, 3)));
1638     }
1639 
1640     @Test
1641     public void shouldSplitAtBegin() {
1642         assertThat(of(1, 2, 3).splitAt(0)).isEqualTo(Tuple.of(empty(), of(1, 2, 3)));
1643     }
1644 
1645     @Test
1646     public void shouldSplitAtEnd() {
1647         assertThat(of(1, 2, 3).splitAt(3)).isEqualTo(Tuple.of(of(1, 2, 3), empty()));
1648     }
1649 
1650     @Test
1651     public void shouldSplitAtOutOfBounds() {
1652         assertThat(of(1, 2, 3).splitAt(5)).isEqualTo(Tuple.of(of(1, 2, 3), empty()));
1653         assertThat(of(1, 2, 3).splitAt(-1)).isEqualTo(Tuple.of(empty(), of(1, 2, 3)));
1654     }
1655 
1656     // -- splitAt(predicate)
1657 
1658     @Test
1659     public void shouldSplitPredicateAtNil() {
1660         assertThat(empty().splitAt(e -> true)).isEqualTo(Tuple.of(empty(), empty()));
1661     }
1662 
1663     @Test
1664     public void shouldSplitPredicateAtNonNil() {
1665         assertThat(of(1, 2, 3).splitAt(e -> e == 2)).isEqualTo(Tuple.of(of(1), of(2, 3)));
1666     }
1667 
1668     @Test
1669     public void shouldSplitAtPredicateBegin() {
1670         assertThat(of(1, 2, 3).splitAt(e -> e == 1)).isEqualTo(Tuple.of(empty(), of(1, 2, 3)));
1671     }
1672 
1673     @Test
1674     public void shouldSplitAtPredicateEnd() {
1675         assertThat(of(1, 2, 3).splitAt(e -> e == 3)).isEqualTo(Tuple.of(of(1, 2), of(3)));
1676     }
1677 
1678     @Test
1679     public void shouldSplitAtPredicateNotFound() {
1680         assertThat(of(1, 2, 3).splitAt(e -> e == 5)).isEqualTo(Tuple.of(of(1, 2, 3), empty()));
1681     }
1682 
1683     // -- splitAtInclusive(predicate)
1684 
1685     @Test
1686     public void shouldSplitInclusivePredicateAtNil() {
1687         assertThat(empty().splitAtInclusive(e -> true)).isEqualTo(Tuple.of(empty(), empty()));
1688     }
1689 
1690     @Test
1691     public void shouldSplitInclusivePredicateAtNonNil() {
1692         assertThat(of(1, 2, 3).splitAtInclusive(e -> e == 2)).isEqualTo(Tuple.of(of(1, 2), of(3)));
1693     }
1694 
1695     @Test
1696     public void shouldSplitAtInclusivePredicateBegin() {
1697         assertThat(of(1, 2, 3).splitAtInclusive(e -> e == 1)).isEqualTo(Tuple.of(of(1), of(2, 3)));
1698     }
1699 
1700     @Test
1701     public void shouldSplitAtInclusivePredicateEnd() {
1702         assertThat(of(1, 2, 3).splitAtInclusive(e -> e == 3)).isEqualTo(Tuple.of(of(1, 2, 3), empty()));
1703     }
1704 
1705     @Test
1706     public void shouldSplitAtInclusivePredicateNotFound() {
1707         assertThat(of(1, 2, 3).splitAtInclusive(e -> e == 5)).isEqualTo(Tuple.of(of(1, 2, 3), empty()));
1708     }
1709 
1710     // -- startsWith
1711 
1712     @Test
1713     public void shouldStartsNilOfNilCalculate() {
1714         assertThat(empty().startsWith(empty())).isTrue();
1715     }
1716 
1717     @Test
1718     public void shouldStartsNilOfNonNilCalculate() {
1719         assertThat(empty().startsWith(of(1))).isFalse();
1720     }
1721 
1722     @Test
1723     public void shouldStartsNilOfNilWithOffsetCalculate() {
1724         assertThat(empty().startsWith(empty(), 1)).isTrue();
1725     }
1726 
1727     @Test
1728     public void shouldStartsNilOfNonNilWithOffsetCalculate() {
1729         assertThat(empty().startsWith(of(1), 1)).isFalse();
1730     }
1731 
1732     @Test
1733     public void shouldStartsNonNilOfNilCalculate() {
1734         assertThat(of(1, 2, 3).startsWith(empty())).isTrue();
1735     }
1736 
1737     @Test
1738     public void shouldStartsNonNilOfNonNilCalculate() {
1739         assertThat(of(1, 2, 3).startsWith(of(1, 2))).isTrue();
1740         assertThat(of(1, 2, 3).startsWith(of(1, 2, 3))).isTrue();
1741         assertThat(of(1, 2, 3).startsWith(of(1, 2, 3, 4))).isFalse();
1742         assertThat(of(1, 2, 3).startsWith(of(1, 3))).isFalse();
1743     }
1744 
1745     @Test
1746     public void shouldStartsNonNilOfNilWithOffsetCalculate() {
1747         assertThat(of(1, 2, 3).startsWith(empty(), 1)).isTrue();
1748     }
1749 
1750     @Test
1751     public void shouldNotStartsNonNilOfNonNilWithNegativeOffsetCalculate() {
1752         assertThat(of(1, 2, 3).startsWith(of(1), -1)).isFalse();
1753     }
1754 
1755     @Test
1756     public void shouldNotStartsNonNilOfNonNilWithOffsetEqualLengthCalculate() {
1757         assertThat(of(1, 2, 3).startsWith(of(3), 3)).isFalse();
1758     }
1759 
1760     @Test
1761     public void shouldNotStartsNonNilOfNonNilWithOffsetEndCalculate() {
1762         assertThat(of(1, 2, 3).startsWith(of(3), 2)).isTrue();
1763     }
1764 
1765     @Test
1766     public void shouldStartsNonNilOfNonNilWithOffsetAtStartCalculate() {
1767         assertThat(of(1, 2, 3).startsWith(of(1), 0)).isTrue();
1768     }
1769 
1770     @Test
1771     public void shouldStartsNonNilOfNonNilWithOffsetCalculate1() {
1772         assertThat(of(1, 2, 3).startsWith(of(2, 3), 1)).isTrue();
1773     }
1774 
1775     @Test
1776     public void shouldStartsNonNilOfNonNilWithOffsetCalculate2() {
1777         assertThat(of(1, 2, 3).startsWith(of(2, 3, 4), 1)).isFalse();
1778     }
1779 
1780     @Test
1781     public void shouldStartsNonNilOfNonNilWithOffsetCalculate3() {
1782         assertThat(of(1, 2, 3).startsWith(of(2, 4), 1)).isFalse();
1783     }
1784 
1785     // -- subSequence(beginIndex)
1786 
1787     @Test
1788     public void shouldReturnNilWhenSubSequenceFrom0OnNil() {
1789         final Seq<Integer> actual = this.<Integer> empty().subSequence(0);
1790         assertThat(actual).isEmpty();
1791     }
1792 
1793     @Test
1794     public void shouldReturnIdentityWhenSubSequenceFrom0OnNonNil() {
1795         final Seq<Integer> actual = of(1).subSequence(0);
1796         assertThat(actual).isEqualTo(of(1));
1797     }
1798 
1799     @Test
1800     public void shouldReturnNilWhenSubSequenceFrom1OnSeqOf1() {
1801         final Seq<Integer> actual = of(1).subSequence(1);
1802         assertThat(actual).isEmpty();
1803     }
1804 
1805     @Test
1806     public void shouldReturnSubSequenceWhenIndexIsWithinRange() {
1807         final Seq<Integer> actual = of(1, 2, 3).subSequence(1);
1808         assertThat(actual).isEqualTo(of(2, 3));
1809     }
1810 
1811     @Test
1812     public void shouldReturnNilWhenSubSequenceBeginningWithSize() {
1813         final Seq<Integer> actual = of(1, 2, 3).subSequence(3);
1814         assertThat(actual).isEmpty();
1815     }
1816 
1817     @Test(expected = IndexOutOfBoundsException.class)
1818     public void shouldThrowWhenSubSequenceOnNil() {
1819         empty().subSequence(1);
1820     }
1821 
1822     @Test(expected = IndexOutOfBoundsException.class)
1823     public void shouldThrowWhenSubSequenceWithOutOfLowerBound() {
1824         of(1, 2, 3).subSequence(-1);
1825     }
1826 
1827     @Test(expected = IndexOutOfBoundsException.class)
1828     public void shouldThrowWhenSubSequenceWithOutOfUpperBound() {
1829         of(1, 2, 3).subSequence(4);
1830     }
1831 
1832     @Test
1833     public void shouldReturnSameInstanceIfSubSequenceStartsAtZero() {
1834         final Seq<Integer> seq = of(1, 2, 3);
1835         assertThat(seq.subSequence(0)).isSameAs(seq);
1836     }
1837 
1838     // -- subSequence(beginIndex, endIndex)
1839 
1840     @Test
1841     public void shouldReturnNilWhenSubSequenceFrom0To0OnNil() {
1842         final Seq<Integer> actual = this.<Integer> empty().subSequence(0, 0);
1843         assertThat(actual).isEmpty();
1844     }
1845 
1846     @Test
1847     public void shouldReturnNilWhenSubSequenceFrom0To0OnNonNil() {
1848         final Seq<Integer> actual = of(1).subSequence(0, 0);
1849         assertThat(actual).isEmpty();
1850     }
1851 
1852     @Test
1853     public void shouldReturnSeqWithFirstElementWhenSubSequenceFrom0To1OnNonNil() {
1854         final Seq<Integer> actual = of(1).subSequence(0, 1);
1855         assertThat(actual).isEqualTo(of(1));
1856     }
1857 
1858     @Test
1859     public void shouldReturnNilWhenSubSequenceFrom1To1OnNonNil() {
1860         final Seq<Integer> actual = of(1).subSequence(1, 1);
1861         assertThat(actual).isEmpty();
1862     }
1863 
1864     @Test
1865     public void shouldReturnSubSequenceWhenIndicesAreWithinRange() {
1866         final Seq<Integer> actual = of(1, 2, 3).subSequence(1, 3);
1867         assertThat(actual).isEqualTo(of(2, 3));
1868     }
1869 
1870     @Test
1871     public void shouldReturnNilWhenOnSubSequenceIndicesBothAreUpperBound() {
1872         final Seq<Integer> actual = of(1, 2, 3).subSequence(3, 3);
1873         assertThat(actual).isEmpty();
1874     }
1875 
1876     @Test(expected = IllegalArgumentException.class)
1877     public void shouldThrowOnSubSequenceOnNonNilWhenBeginIndexIsGreaterThanEndIndex() {
1878         of(1, 2, 3).subSequence(1, 0);
1879     }
1880 
1881     @Test(expected = IllegalArgumentException.class)
1882     public void shouldThrowOnSubSequenceOnNilWhenBeginIndexIsGreaterThanEndIndex() {
1883         empty().subSequence(1, 0);
1884     }
1885 
1886     @Test(expected = IndexOutOfBoundsException.class)
1887     public void shouldThrowOnSubSequenceOnNonNilWhenBeginIndexExceedsLowerBound() {
1888         of(1, 2, 3).subSequence(-1, 2);
1889     }
1890 
1891     @Test(expected = IndexOutOfBoundsException.class)
1892     public void shouldThrowOnSubSequenceOnNilWhenBeginIndexExceedsLowerBound() {
1893         empty().subSequence(-1, 2);
1894     }
1895 
1896     @Test(expected = IndexOutOfBoundsException.class)
1897     public void shouldThrowWhenSubSequence2OnNil() {
1898         empty().subSequence(0, 1);
1899     }
1900 
1901     @Test(expected = IndexOutOfBoundsException.class)
1902     public void shouldThrowOnSubSequenceWhenEndIndexExceedsUpperBound() {
1903         of(1, 2, 3).subSequence(1, 4).mkString(); // force computation of last element, e.g. because Stream is lazy
1904     }
1905 
1906     @Test(expected = IllegalArgumentException.class)
1907     public void shouldThrowOnSubSequenceWhenBeginIndexIsGreaterThanEndIndex() {
1908         of(1, 2, 3).subSequence(2, 1).mkString(); // force computation of last element, e.g. because Stream is lazy
1909     }
1910 
1911     @Test
1912     public void shouldReturnSameInstanceIfSubSequenceStartsAtZeroAndEndsAtLastElement() {
1913         final Seq<Integer> seq = of(1, 2, 3);
1914         assertThat(seq.subSequence(0, 3)).isSameAs(seq);
1915     }
1916 
1917     // -- search(element)
1918 
1919     @Test
1920     public void shouldSearchIndexForPresentElements() {
1921         assertThat(of(1, 2, 3, 4, 5, 6).search(3)).isEqualTo(2);
1922     }
1923 
1924     @Test
1925     public void shouldSearchNegatedInsertionPointMinusOneForAbsentElements() {
1926         assertThat(empty().search(42)).isEqualTo(-1);
1927         assertThat(of(10, 20, 30).search(25)).isEqualTo(-3);
1928     }
1929 
1930     // -- search(element,comparator)
1931 
1932     @Test
1933     public void shouldSearchIndexForPresentElementsUsingComparator() {
1934         assertThat(of(1, 2, 3, 4, 5, 6).search(3, Integer::compareTo)).isEqualTo(2);
1935     }
1936 
1937     @Test
1938     public void shouldSearchNegatedInsertionPointMinusOneForAbsentElementsUsingComparator() {
1939         assertThat(this.<Integer> empty().search(42, Integer::compareTo)).isEqualTo(-1);
1940         assertThat(of(10, 20, 30).search(25, Integer::compareTo)).isEqualTo(-3);
1941     }
1942 
1943     // -- IndexedSeq special cases
1944 
1945     @Test
1946     public void shouldTestIndexedSeqStartsWithNonIndexedSeq() {
1947         assertThat(of(1, 3, 4).startsWith(Stream.of(1, 3))).isTrue();
1948         assertThat(of(1, 2, 3, 4).startsWith(Stream.of(1, 2, 4))).isFalse();
1949         assertThat(of(1, 2).startsWith(Stream.of(1, 2, 4))).isFalse();
1950     }
1951 
1952     @Test
1953     public void shouldTestIndexedSeqEndsWithNonIndexedSeq() {
1954         assertThat(of(1, 3, 4).endsWith(Stream.of(3, 4))).isTrue();
1955         assertThat(of(1, 2, 3, 4).endsWith(Stream.of(2, 3, 5))).isFalse();
1956     }
1957 
1958     @Test
1959     public void lift() {
1960         final Function1<Integer, Option<String>> lifted = of("a", "b", "c").lift();
1961         assertThat(lifted.apply(1).get()).isEqualTo("b");
1962         assertThat(lifted.apply(-1).isEmpty()).isTrue();
1963         assertThat(lifted.apply(3).isEmpty()).isTrue();
1964     }
1965 
1966     @Test
1967     public void withDefaultValue() {
1968         final Function1<Integer, String> withDef = of("a", "b", "c").withDefaultValue("z");
1969         assertThat(withDef.apply(2)).isEqualTo("c");
1970         assertThat(withDef.apply(-1)).isEqualTo("z");
1971         assertThat(withDef.apply(3)).isEqualTo("z");
1972     }
1973 
1974     @Test
1975     public void withDefault() {
1976         final Function1<Integer, String> withDef = of("a", "b", "c").withDefault(Object::toString);
1977         assertThat(withDef.apply(2)).isEqualTo("c");
1978         assertThat(withDef.apply(-1)).isEqualTo("-1");
1979         assertThat(withDef.apply(3)).isEqualTo("3");
1980     }
1981 
1982     // -- transpose()
1983 
1984     @Test
1985     public void shouldTransposeIfEmpty() {
1986         final Seq<Seq<Integer>> actual = empty();
1987         assertThat(transpose(actual)).isSameAs(actual);
1988     }
1989 
1990     @Test
1991     public void shouldTransposeIfIs1x0() {
1992         final Seq<Seq<Integer>> actual = of(empty());
1993         assertThat(transpose(actual)).isSameAs(actual);
1994     }
1995 
1996     @Test
1997     public void shouldTransposeIfIs1x1() {
1998         final Seq<Seq<Integer>> actual = of(of(1));
1999         assertThat(transpose(actual)).isSameAs(actual);
2000     }
2001 
2002     @Test
2003     public void shouldTransposeIfSingleValued() {
2004         final Seq<Seq<Integer>> actual = of(of(0));
2005         final Seq<Seq<Integer>> expected = of(of(0));
2006         assertThat(transpose(actual)).isEqualTo(expected);
2007     }
2008 
2009     @Test
2010     @SuppressWarnings("unchecked")
2011     public void shouldTransposeIfMultiValuedColumn() {
2012         final Seq<Seq<Integer>> actual = of(of(0, 1, 2));
2013         final Seq<Seq<Integer>> expected = of(of(0), of(1), of(2));
2014         assertThat(transpose(actual)).isEqualTo(expected);
2015     }
2016 
2017     @Test
2018     @SuppressWarnings("unchecked")
2019     public void shouldTransposeIfMultiValuedRow() {
2020         final Seq<Seq<Integer>> actual = of(of(0), of(1), of(2));
2021         final Seq<Seq<Integer>> expected = of(of(0, 1, 2));
2022         assertThat(transpose(actual)).isEqualTo(expected);
2023     }
2024 
2025     @Test
2026     @SuppressWarnings("unchecked")
2027     public void shouldTransposeIfMultiValuedIfSymmetric() {
2028         final Seq<Seq<Integer>> actual = of(
2029                 of(1, 2, 3),
2030                 of(4, 5, 6),
2031                 of(7, 8, 9));
2032         final Seq<Seq<Integer>> expected = of(
2033                 of(1, 4, 7),
2034                 of(2, 5, 8),
2035                 of(3, 6, 9));
2036         assertThat(transpose(actual)).isEqualTo(expected);
2037     }
2038 
2039     @Test
2040     @SuppressWarnings("unchecked")
2041     public void shouldTransposeIfMultiValuedWithMoreColumnsThanRows() {
2042         final Seq<Seq<Integer>> actual = of(
2043                 of(1, 2, 3),
2044                 of(4, 5, 6));
2045         final Seq<Seq<Integer>> expected = of(
2046                 of(1, 4),
2047                 of(2, 5),
2048                 of(3, 6));
2049         assertThat(transpose(actual)).isEqualTo(expected);
2050     }
2051 
2052     @Test
2053     @SuppressWarnings("unchecked")
2054     public void shouldTransposeIfMultiValuedWithMoreRowsThanColumns() {
2055         final Seq<Seq<Integer>> actual = of(
2056                 of(1, 2),
2057                 of(3, 4),
2058                 of(5, 6));
2059         final Seq<Seq<Integer>> expected = of(
2060                 of(1, 3, 5),
2061                 of(2, 4, 6));
2062         assertThat(transpose(actual)).isEqualTo(expected);
2063     }
2064 
2065     @Test
2066     @SuppressWarnings("unchecked")
2067     public void shouldBeEqualIfTransposedTwice() {
2068         final Seq<Seq<Integer>> actual = of(
2069                 of(1, 2, 3),
2070                 of(4, 5, 6));
2071         final Seq<? extends Seq<Integer>> transposed = transpose(actual);
2072         assertThat(transpose(transposed)).isEqualTo(actual);
2073     }
2074 
2075     @Test(expected = IllegalArgumentException.class)
2076     @SuppressWarnings("unchecked")
2077     public void shouldNotTransposeForMissingOrEmptyValues() {
2078         final Seq<Seq<Integer>> actual = of(
2079                 of(),
2080                 of(0, 1),
2081                 of(2, 3, 4, 5),
2082                 of(),
2083                 of(6, 7, 8));
2084         transpose(actual);
2085     }
2086 
2087     // -- spliterator
2088 
2089     @Test
2090     public void shouldNotHaveSortedSpliterator() {
2091         assertThat(of(1, 2, 3).spliterator().hasCharacteristics(Spliterator.SORTED)).isFalse();
2092     }
2093 
2094     @Test
2095     public void shouldHaveOrderedSpliterator() {
2096         assertThat(of(1, 2, 3).spliterator().hasCharacteristics(Spliterator.ORDERED)).isTrue();
2097     }
2098 
2099     @Test
2100     public void shouldNotHaveDistinctSpliterator() {
2101         assertThat(of(1, 2, 3).spliterator().hasCharacteristics(Spliterator.DISTINCT)).isFalse();
2102     }
2103 
2104     // -- isSequential()
2105 
2106     @Test
2107     public void shouldReturnTrueWhenIsSequentialCalled() {
2108         assertThat(of(1, 2, 3).isSequential()).isTrue();
2109     }
2110 
2111 }